package com.bjx.flow.mmx.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bjx.common.core.util.SpringUtil;
import com.bjx.flow.mmx.bean.MmxFlowData;
import com.bjx.flow.mmx.bean.MmxNextNodeData;
import com.bjx.flow.mmx.bean.MmxNodeData;
import com.bjx.flow.mmx.constant.MmxNodeConstant;
import com.bjx.flow.mmx.domain.bo.MmxNodeFlowBO;
import com.bjx.flow.mmx.service.MmxFlowDataService;
import com.bjx.flow.mmx.task.MmxAbstractNodeFlowDispose;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @desc: 流程数据操作实现类
 * @author: liushuai
 * @date: 2023/1/31 10:52
 */
@Service
public class MmxFlowDataServiceImpl implements MmxFlowDataService {
    @Override
    public MmxFlowData checkFlowData(String flowData) {
        if (!JSONUtil.isTypeJSONObject(flowData)) {
            throw new IllegalArgumentException("The flowData parameter is not a JSONObject");
        }
        JSONObject jsonObject = new JSONObject(flowData);
        MmxFlowData flowObj = Optional.ofNullable(JSONUtil.toBean(jsonObject, MmxFlowData.class)).orElse(new MmxFlowData());
        if (StrUtil.isEmpty(flowObj.getDefinitionKey())) {
            throw new NullPointerException("definitionKey cannot be empty");
        }
        //流程节点
        List<MmxNodeData> nodes = flowObj.getNodes();
        if (CollectionUtil.isEmpty(nodes)) {
            throw new RuntimeException("nodes cannot be empty ");
        }
        MmxNodeData startNode = null;
        MmxNodeData endNode = null;
        for (MmxNodeData nodeData : nodes) {
            if (StrUtil.isEmpty(nodeData.getId())) {
                throw new NullPointerException("node id cannot be empty");
            }
            String type = nodeData.getType();
            if (StrUtil.isEmpty(type)) {
                throw new NullPointerException("node type cannot be empty");
            }
            if (MmxNodeConstant.START.equals(type)) {
                startNode = nodeData;
            }
            if (MmxNodeConstant.END.equals(type)) {
                endNode = nodeData;
            }
        }
        if (startNode == null) {
            throw new NullPointerException("start node cannot be empty");
        }
        if (endNode == null) {
            throw new NullPointerException("end node cannot be empty");
        }
        return flowObj;
    }

    @Override
    public MmxNextNodeData taskFlow(String flowData, String nodeId, Map<String, Object> variables) {
        //解析流程数据
        JSONObject jsonObject = new JSONObject(flowData);
        //转为流程对象
        MmxFlowData flowObj = JSONUtil.toBean(jsonObject, MmxFlowData.class);
        //获取所有的流程节点
        List<MmxNodeData> nodes = flowObj.getNodes();
        //开始节点
        MmxNodeData startNode = null;
        //当前节点
        MmxNodeData currentNode = null;
        for (MmxNodeData node : nodes) {
            if (MmxNodeConstant.START.equals(node.getType())) {
                startNode = node;
            }
            if (node.getId().equals(nodeId)) {
                currentNode = node;
            }
        }
        //当没有节点id时默认为开始节点为当前节点
        if (nodeId == null) {
            currentNode = startNode;
        }
        //获取节点数据的任务节点处理对象
        MmxAbstractNodeFlowDispose taskNode = SpringUtil.getBean(currentNode.getType());
        //调用任务节点处理对象的执行方法，获取下一个任务节点的节点列表
        MmxNodeFlowBO nodeFlowBO = taskNode.execute(flowObj, currentNode, variables);
        return MmxNextNodeData.builder()
                .currentNode(currentNode)
                .startNodeId(startNode.getId())
                .nodeDataList(nodeFlowBO.getNodeData())
                .flowNodeType(nodeFlowBO.getNodeType())
                .variables(variables)
                .build();
    }


}
